<template>
  <div v-if="!isRequest" class="prompt-masker flex">
    <div class="prompt">
      <h2 class="prompt-title">{{ title }}</h2>
      <template v-if="showNickName">
        <input
          class="input-name"
          ref="nickNameRef"
          autofocus
          autocomplete="false"
          maxlength="8"
          :value="nickName"
          @compositionstart="compositStart"
          @compositionend="compositEnd"
          @input="handleInput($event)"
          @keyup.enter.prevent="next('sex')"
        />
        <el-button
          color="rgb(74, 89, 100)"
          type="info"
          :disabled="!nickName"
          class="prompt-button-name"
          size="large"
          round
          @click="next('sex')"
          >下一步</el-button
        ></template
      >
      <template v-if="showSex"
        ><el-radio-group class="radio-sex" v-model="user.sex">
          <el-radio label="男">男</el-radio>
          <el-radio label="女">女</el-radio>
        </el-radio-group>
        <div class="prompt-button">
          <el-button
            color="rgb(74, 89, 100)"
            type="info"
            class="prompt-button-sex"
            size="large"
            round
            @click="previous('name')"
            >上一步</el-button
          >
          <el-button
            class="prompt-button-sex"
            color="rgb(74, 89, 100)"
            type="info"
            size="large"
            round
            @click="next('birth')"
            >下一步</el-button
          >
        </div></template
      >
      <template v-if="showBirth">
        <select-birth
          v-model:birthday="user.birthday"
          :disabled="isLoading"
        ></select-birth>
        <div class="prompt-button">
          <el-button
            color="rgb(74, 89, 100)"
            type="info"
            :disabled="isLoading"
            class="prompt-button-birth"
            size="large"
            round
            @click="previous('sex')"
            >上一步</el-button
          >
          <el-button
            class="prompt-button-birth"
            color="rgb(74, 89, 100)"
            type="info"
            :disabled="isLoading"
            size="large"
            :loading="isLoading"
            @click="uploadUserMessage"
            round
            ><template #loading><Loading /></template>完成</el-button
          >
        </div></template
      >
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, onBeforeMount, onBeforeUnmount, customRef, nextTick } from "vue";
import selectBirth from "@/components/selectBirth.vue";
import type { Ref } from "@vue/runtime-core";
import { useUserPinia } from "../pinia/user";
import { ElMessage } from "element-plus";
import Cookie from "../plugins/cookie";
import { useRouter } from "vue-router";
import LoadingBar from "../plugins/loadingBar";

const userStore = useUserPinia();
const router = useRouter();

/**
 * 该组件的根元素的高度
 */
let winHei = ref<string>("");

/**
 * 浏览器的可视高度改变则组件的根元素的高度也随之改变
 */
const handleToWid: () => void = (): void => {
  // 获取浏览器的可视高度
  const hei: number =
    window.innerHeight ||
    document.body.clientHeight ||
    document.documentElement.clientHeight;
  if (hei <= 450) winHei.value = "450px";
  else winHei.value = `${hei}px`;
};

/**
 * 是否正在请求判断用户是否第一次登录接口
 */
const isRequest = ref<boolean>(false);
onBeforeMount(() => {
  if (userStore.isFirst) {
    // 初始化组件根元素的高度
    handleToWid();
    // 给浏览器添加监听窗口大小变化的事件
    window.addEventListener("resize", handleToWid);
  } else {
    isRequest.value = true;
    const loadingBar = new LoadingBar();
    loadingBar.start();
    userStore
      .isUserFirstLogin()
      .then((code: number) => {
        if (code === 1) {
          if (userStore.isFirst) {
            loadingBar.finsh();
            isRequest.value = false;
            nextTick(() => {
              // 初始化组件根元素的高度
              handleToWid();
              // 给浏览器添加监听窗口大小变化的事件
              window.addEventListener("resize", handleToWid);
            });
          } else {
            loadingBar.unMount();
            router.replace("/");
          }
        } else if (code === -1) {
          Cookie.deleteCookie("token");
          loadingBar.unMount();
          ElMessage.error("token已失效，请重新登录");
          router.replace({ name: "login" });
        } else {
          loadingBar.unMount();
          router.push("/404");
        }
      })
      .catch(() => {
        loadingBar.unMount();
        router.push("/404");
      });
  }
});

/* 设置昵称逻辑 */
/**
 * 创建自定义响应属性
 * @param value - 属性值
 */
const useRef: (value: string) => Ref<string> = (value: string): Ref<string> =>
  customRef((track, trigger) => ({
    get(): string {
      track();
      return value;
    },
    set(newValue: string): void {
      value = newValue.trim();
      trigger();
    },
  }));

// 用户的昵称
const nickName: Ref<string> = useRef("");
/**
 * 文本段落的组成是否完成或取消时
 */
const isCompositEnd = ref<boolean>(true);
// 开始输入中文
const compositStart = () => {
  isCompositEnd.value = false;
};
// 输入中文结束
const compositEnd = (e: Event) => {
  isCompositEnd.value = true;
  handleInput(e);
};
const handleInput = (e: Event) => {
  if (isCompositEnd.value) nickName.value = (e.target as HTMLInputElement).value;
};

/**
 * 是否显示昵称设置栏
 */
const showNickName = ref<boolean>(true);
/**
 * 是否显示性别设置栏
 */
const showSex = ref<boolean>(false);
/**
 * 是否显示生日设置栏
 */
const showBirth = ref<boolean>(false);
/**
 * 对话框的标题
 */
const title = ref<string>("Give yourself a nice name");

// 针对性别选择和生日选择用户按下Enter键后的操作
const pressEnter = (type: "birth" | "finsh") => {
  switch (type) {
    case "birth":
      next("birth");
      break;
    case "finsh":
      uploadUserMessage();
      break;
  }
};

const revokeSexKeyUp = (e: KeyboardEvent) => {
  const key: string = e.key.toLowerCase();
  if (key === "arrowright" && user.value.sex !== "女") user.value.sex = "女";
  if (key === "arrowleft" && user.value.sex !== "男") user.value.sex = "男";
  if (key === "enter") pressEnter("birth");
};
const revokeBirthKeyUp = (e: KeyboardEvent) => {
  const key: string = e.key.toLowerCase();
  if (key === "enter") pressEnter("finsh");
};

/**
 * 给昵称输入框一个ref属性
 */
const nickNameRef = ref<HTMLInputElement>();
// 上一步的操作
const previous = (type: string): void => {
  switch (type) {
    case "name":
      document.removeEventListener("keyup", revokeSexKeyUp);
      showSex.value = false;
      title.value = "Give yourself a nice name";
      showNickName.value = true;
      nextTick(() => nickNameRef.value?.focus());
      break;
    case "sex":
      document.removeEventListener("keyup", revokeBirthKeyUp);
      showBirth.value = false;
      title.value = "What is your gender?";
      showSex.value = true;
      document.addEventListener("keyup", revokeSexKeyUp);
      break;
  }
};

// 下一步的操作
const next = (str: string): void => {
  switch (str) {
    case "sex":
      if (nickName.value.length) {
        showNickName.value = false;
        showSex.value = true;
        title.value = "What is your gender?";
        setTimeout(() => document.addEventListener("keyup", revokeSexKeyUp), 0);
      }
      break;
    case "birth":
      document.removeEventListener("keyup", revokeSexKeyUp);
      showSex.value = false;
      showBirth.value = true;
      title.value = "What's your birth date?";
      document.addEventListener("keyup", revokeBirthKeyUp);
      break;
  }
};

/* 设置性别 */
const user = ref<{
  sex: '男' | '女';
  birthday: Date;
}>({
  sex: "男",
  birthday: new Date(),
});

const isLoading = ref<boolean>(false);
// 开始上传用户的信息
const uploadUserMessage = (): void => {
  if (isLoading.value) return;
  isLoading.value = true;
  userStore
    .setUserInfo({
      nickName: nickName.value,
      sex: user.value.sex,
      birthday: user.value.birthday,
    })
    .then((code: number) => {
      isLoading.value = false;
      if (code === 1) router.replace("/");
      else if (code === -1) {
        Cookie.deleteCookie("token");
        ElMessage.error("token已失效，请重新登录");
        router.replace({ name: "login" });
      } else ElMessage.error("设置失败，请在尝试一次");
    })
    .catch(() => {
      isLoading.value = false;
      ElMessage.error("设置失败，请在尝试一次");
    });
};

// 组件卸载前移除事所有的事件监听
onBeforeUnmount(() => {
  window.removeEventListener("resize", handleToWid);
  document.removeEventListener("keyup", revokeSexKeyUp);
  document.removeEventListener("keyup", revokeBirthKeyUp);
});
</script>

<style lang="scss" scoped>
.prompt {
  border-radius: 10px;
  background-color: #fff;
  box-sizing: border-box;
  width: 450px;
  min-height: 230px;
  box-shadow: 0px 16px 48px 16px rgba(0, 0, 0, 0.08), 0px 12px 32px rgba(0, 0, 0, 0.12),
    0px 8px 16px -8px rgba(0, 0, 0, 0.16);
  padding: 20px 50px;
  position: relative;
  ::selection {
    color: #fff;
    background: #409eff;
  }

  &-title {
    margin: 0;
    text-align: center;
  }

  &-masker {
    position: relative;
    height: v-bind(winHei);
    background-color: rgba(0, 0, 0, 0.4);
    padding: 0 30px;
  }

  &-button {
    display: flex;
    justify-content: space-between;

    &-name {
      position: absolute;
      bottom: 20px;
      left: 50px;
      width: calc(100% - 100px);
    }

    &-sex {
      width: 40%;
    }

    &-birth {
      width: 40%;
    }
  }
}

.input {
  &-name {
    margin: 30px 0;
    padding: 10px 0 10px;
    border: {
      top: 0;
      left: 0;
      right: 0;
      bottom-width: 1.5px;
    }
    outline: none;
    width: 100%;
    font-size: 17px;
  }
}

.radio-sex {
  margin: 40px 60px;

  :deep(.el-radio__inner) {
    border-color: rgb(50, 59, 69);

    &:hover {
      border-color: rgb(15, 20, 25);
    }
  }

  :deep(.el-radio__label) {
    font-size: 17px;
  }

  :deep(.el-radio__input.is-checked .el-radio__inner) {
    background-color: rgb(15, 20, 25);
    border-color: rgb(15, 20, 25);
  }

  :deep(.el-radio__input.is-checked + .el-radio__label) {
    color: rgb(15, 20, 25);
  }
}
</style>
